import axios from "axios";
import type { AxiosError } from "axios";
import { isCircuitOpen, reportFailure, resetBreaker } from "./circuitBreaker";
import { retryRequest } from "./retryHandler";
import { getFallbackResponse } from "./fallbackHandler";

export const http = axios.create({
  timeout: 10000,
  headers: {
    "Content-Type": "application/json",
  },
});

// 请求拦截器
http.interceptors.request.use(
  (config) => {
    const circuitKey = config.url!;
    if (isCircuitOpen(circuitKey)) {
      return Promise.reject(new Error("请求已熔断"));
    }

    // DeepSeek-GPT的sk码
    if (config.params.deepseek == "Y" || config.data.deepseek == "Y") {
      const token = config.params.gptToken || config.data.gptToken;
      config.headers["Authorization"] = "Bearer " + token;
    }

    // 普通的接口请求
    if (sessionStorage.getItem("token")) {
      const token = sessionStorage.getItem("token");
      config.headers["Authorization"] = "Bearer " + token;
    }
    return config;
  },
  (error) => {
    Promise.reject(error);
  }
);

// 响应拦截器
http.interceptors.response.use(
  (response) => {
    resetBreaker(response.config.url!);
    return response.data;
  },
  async (error: AxiosError) => {
    const config = error.config!;
    const url = config.url!;
    const status = error.response?.status ?? 0;

    const shouldRetry = [429, 500, 503].includes(status);
    const maxRetry = (config as any)._retryCount ?? 2;

    try {
      if (shouldRetry) {
        return await retryRequest(config, maxRetry);
      }
    } catch (retryErr) {
      reportFailure(url, 3, 10000);
    }

    // 降级数据
    const fallback = getFallbackResponse(config);

    console.log(error);
    const messages: Record<number, string> = {
      400: "上下文过长",
      401: "认证失败",
      402: "余额不足",
      422: "参数错误",
      429: "请求速率达到上限",
      500: "服务器故障",
      503: "服务器繁忙",
      0: "服务器发生错误，请检查服务器。",
    };
    ElMessage({
      showClose: true,
      message: messages[status] || "网络错误",
      type: "error",
      plain: true,
    });

    return Promise.reject(fallback);
  }
);
